import locale
import os
import re
import sys
import time
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox
from tkinter import ttk

'''
批量重命名文件步骤
1、运行程序，首先弹出一个弹窗询问“选择文件夹”还是“批量选择文件”
2、选择对象
3、在文本框中按默认顺序打印所有选择的文件
4、对文件排序
5、在文本框中打印排序后的文件
6、选择方式重命名，并在文本框中展示前后对比
'''


def choose_files_or_folder():
    root = tk.Tk()
    root.title("请选择")

    # 设置大小，位置
    root = set_container_size(root, proportion=7)

    # 窗口置顶
    root.attributes('-topmost', 'true')

    # 设置对话框的内容
    label = tk.Label(root, text="你选择\n'文件夹' or '多个文件'", font=("Microsoft YaHei UI Light", 12, "bold"))
    label.pack(pady=20)

    # 存储用户的选择，默认是"选择多个文件"
    user_response = "选择多个文件"

    # 定义按钮的回调函数
    def on_button1_click():
        nonlocal user_response
        user_response = "选择文件夹"
        root.destroy()

    def on_button2_click():
        nonlocal user_response
        user_response = "选择多个文件"
        root.destroy()

    # 创建自定义按钮
    button1 = tk.Button(root, text="文件夹", command=on_button1_click)
    button1.pack(side=tk.LEFT, padx=20)

    button2 = tk.Button(root, text="多个文件", command=on_button2_click)
    button2.pack(side=tk.RIGHT, padx=20)

    def on_closing():
        # 关闭窗口并退出程序
        sys.exit(0)

    # 监听窗口关闭事件
    root.protocol("WM_DELETE_WINDOW", on_closing)

    root.mainloop()

    # 返回用户的选择
    return user_response


def center_window(container, window_width, window_height):
    # 让窗口居中显示

    # 获取屏幕的宽度和高度
    screen_width = container.winfo_screenwidth()
    screen_height = container.winfo_screenheight()

    # 计算窗口居中的位置
    x_position = (screen_width - window_width) // 2
    y_position = (screen_height - window_height) // 2

    # 设置窗口的大小和位置
    container.geometry(f"{window_width}x{window_height}+{x_position}+{y_position}")

    return container


def set_container_size(container, proportion: int):
    # 设置窗口大小和居中

    # 获取屏幕的宽度和高度
    screen_width = container.winfo_screenwidth()
    screen_height = container.winfo_screenheight()

    # 设置窗口的大小为屏幕分辨率的 1/4
    window_width = screen_width // proportion
    window_height = screen_height // proportion

    # 计算窗口居中的位置
    x_position = (screen_width - window_width) // 2
    y_position = (screen_height - window_height) // 2

    # 设置窗口的大小和位置
    container.geometry(f"{window_width}x{window_height}+{x_position}+{y_position}")

    return container


def get_files_in_folder(folder):
    # 获取文件夹下所有文件，不包括子文件夹文件
    files = []

    for item in os.listdir(folder):
        item_path = os.path.join(folder, item)
        if os.path.isfile(item_path):
            files.append(item_path)

    return files


def get_files(choice):
    if choice == "选择多个文件":
        # 弹出文件选择器，可多选文件
        return list(filedialog.askopenfilenames())
    else:
        # 弹出文件夹选择器
        return get_files_in_folder(filedialog.askdirectory())


def sort_by_file_size(disordered_files_path_list, text_box, flag, old_new_name_dict):
    files_size_list = []
    files_name_size_dict = {}
    global parent_folder

    for e in disordered_files_path_list:
        file_size = os.path.getsize(parent_folder + os.sep + e)
        file_name = os.path.basename(e)

        files_size_list.append(file_size)
        files_name_size_dict[file_name] = file_size

    sort_by_basis(text_box, flag, files_size_list, files_name_size_dict, old_new_name_dict)


def sort_by_filename(disordered_files_list, text_box, flag, old_new_name_dict):
    global ordered_files_list
    file_basename_list = []

    # 获取基本名
    for i in disordered_files_list:
        file_basename = os.path.basename(i)
        file_basename_list.append(file_basename)

    # 排序
    locale.setlocale(locale.LC_ALL, 'zh_CN.UTF-8')
    ordered_files_list = sorted(file_basename_list, key=windows_sort_key)

    # Flag = True，按照名称从A-Z排序
    if not flag:
        ordered_files_list.reverse()

    # 清空文本框
    text_box.delete(1.0, tk.END)

    # 展示排序后的文件基本名
    if not old_new_name_dict:
        for j in ordered_files_list:
            content = j + os.linesep
            text_box.insert(tk.END, content)
    else:
        for j in ordered_files_list:
            content = j + '--->' + old_new_name_dict[j] + os.linesep
            text_box.insert(tk.END, content)


def windows_sort_key(_file_name):
    # 将数字部分提取出来，转换为整数
    parts = re.split('([0-9]+)', _file_name)
    parts = [int(part) if part.isdigit() else part for part in parts]

    # 使用 locale.strxfrm 对非数字部分排序
    parts = [locale.strxfrm(str(part)) if isinstance(part, str) else part for part in parts]

    return parts


def sort_by_file_modification_time(disordered_files_path_set, text_box, flag, old_new_name_dict):
    modification_time_list = []
    name_modification_time_dict = {}
    global parent_folder

    for e in disordered_files_path_set:
        modification_time = os.path.getmtime(parent_folder + os.sep + e)
        filename = os.path.basename(e)
        modification_time_list.append(modification_time)
        name_modification_time_dict[filename] = modification_time

    sort_by_basis(text_box, flag, modification_time_list, name_modification_time_dict, old_new_name_dict)


def sort_by_file_type_name(disordered_files_path_set, text_box, flag, old_new_name_dict):
    file_type_name_list = []
    name_file_type_name_dict = {}

    for e in disordered_files_path_set:
        file_type_name = e.split(sep='.')[-1]
        filename = os.path.basename(e)

        file_type_name_list.append(file_type_name)
        name_file_type_name_dict[filename] = file_type_name

    sort_by_basis(text_box, flag, file_type_name_list, name_file_type_name_dict, old_new_name_dict)


def sort_by_basis(text_box, flag, basis_list, name_basis_dict, old_new_name_dict):
    global ordered_files_list
    ordered_files_list = []

    basis_list.sort(reverse=flag)

    for i in basis_list:
        temp_list = []
        for k, v in name_basis_dict.items():
            if v == i:
                if k not in ordered_files_list:
                    temp_list.append(k)

        locale.setlocale(locale.LC_ALL, 'zh_CN.UTF-8')
        ordered_files_list.extend(sorted(temp_list, key=windows_sort_key))

    text_box.delete(1.0, tk.END)

    if not old_new_name_dict:
        for j in ordered_files_list:
            content = j + os.linesep
            text_box.insert(tk.END, content)
    else:
        for j in ordered_files_list:
            content = j + '--->' + old_new_name_dict[j] + os.linesep
            text_box.insert(tk.END, content)


def do_rename(filenames_list, new_filenames_list, old_new_files_dict):
    global parent_folder

    # 为避免命名冲突，先批量重命名为临时名
    temp_names_list = []

    for i in range(len(filenames_list)):
        old_name = parent_folder + os.sep + filenames_list[i]
        temp_name = parent_folder + os.sep + str(int(time.time() * 1000))
        time.sleep(0.001)

        try:
            os.rename(old_name, temp_name)
            temp_names_list.append(temp_name)
            old_new_files_dict[old_name] = temp_name
        except Exception:  # noqa
            rtton(old_new_files_dict)
            messagebox.showerror(message="出现错误，批量重命名失败")
            sys.exit(0)

    # 再把临时名重命名为最终名
    for i in range(len(temp_names_list)):
        old_name = temp_names_list[i]
        new_name = parent_folder + os.sep + new_filenames_list[i]

        for k, v in old_new_files_dict.items():
            if v == old_name:
                old_new_files_dict[k] = new_name
                break

        try:
            os.rename(old_name, new_name)
        except Exception:  # noqa
            rtton(old_new_files_dict)
            messagebox.showerror(message="出现错误，批量重命名失败")
            sys.exit(0)

    # 能执行到这说明重命名成功
    messagebox.showinfo(message='批量重命名成功')
    sys.exit(0)


def show_in_text_box(text_box, filenames_list, new_filenames_list, old_new_names_dict):
    # 清空文本框
    text_box.delete(1.0, tk.END)

    # 展示
    for i in range(len(filenames_list)):
        content = filenames_list[i] + ' ---> ' + new_filenames_list[i] + os.linesep
        old_new_names_dict[filenames_list[i]] = new_filenames_list[i]
        text_box.insert(tk.END, content)


def replace_str(filenames_list, frame_1):
    old_str = tk.StringVar()
    new_str = tk.StringVar()
    new_filenames_list = []
    old_new_names_dict = {}
    old_new_files_dict = {}

    if True:
        label_1 = ttk.Label(frame_1, text='查找字符串：')
        label_1.place(relx=0, rely=0, relwidth=0.2, relheight=0.1)
        entry_1 = ttk.Entry(frame_1, textvariable=old_str)
        entry_1.place(relx=0.2, rely=0, relwidth=0.8, relheight=0.1)

        label_2 = ttk.Label(frame_1, text='替换为：')
        label_2.place(relx=0, rely=0.1, relwidth=0.2, relheight=0.1)
        entry_2 = ttk.Entry(frame_1, textvariable=new_str)
        entry_2.place(relx=0.2, rely=0.1, relwidth=0.8, relheight=0.1)

        # 创建一个Text组件
        text_box = tk.Text(frame_1, wrap=tk.NONE, font=('Arial', 20, 'bold'))  # wrap=tk.NONE 表示不自动换行
        text_box.place(relwidth=0.97, relheight=0.67, relx=0, rely=0.3)

        # 创建竖向滚动条
        v_scrollbar = ttk.Scrollbar(frame_1, orient="vertical", command=text_box.yview)
        v_scrollbar.place(relwidth=0.03, relheight=0.7, relx=0.97, rely=0.3)

        # 创建横向滚动条
        h_scrollbar = ttk.Scrollbar(frame_1, orient="horizontal", command=text_box.xview)
        h_scrollbar.place(relwidth=0.9, relheight=0.03, relx=0, rely=0.97)

        # 配置Text组件的滚动条
        text_box.configure(yscrollcommand=v_scrollbar.set, xscrollcommand=h_scrollbar.set)

    # 默认按照名称从A-Z排序
    sort_by_filename(filenames_list, text_box, flag=True, old_new_name_dict={})

    def preview_btn_clicked():
        nonlocal new_filenames_list
        nonlocal filenames_list
        nonlocal old_new_names_dict
        nonlocal combo
        nonlocal do_btn

        _old_str = old_str.get()
        _new_str = new_str.get()
        new_filenames_list = []

        # 是否允许替换扩展名
        flag = messagebox.askyesno(message='是否允许替换扩展名？')

        # 替换操作
        for i in filenames_list:
            if _old_str in i:
                if flag:
                    modified_name = i.replace(_old_str, _new_str)
                    new_filenames_list.append(modified_name)
                else:
                    i_list = i.split('.')
                    # 文件扩展名
                    file_extension_name = i_list[-1]
                    # 去除扩展名后的文件名
                    file_name_without_extension_name = i_list[0]

                    modified_name = file_name_without_extension_name.replace(_old_str,
                                                                             _new_str) + '.' + file_extension_name
                    new_filenames_list.append(modified_name)
            else:
                new_filenames_list.append(i)

        show_in_text_box(text_box, filenames_list, new_filenames_list, old_new_names_dict)

        combo.current(0)
        do_btn.state(['!disabled'])

    preview_btn = ttk.Button(frame_1, text='预览', command=preview_btn_clicked)
    preview_btn.place(relx=0.4, rely=0.2, relwidth=0.3, relheight=0.1)

    def do_btn_clicked():
        nonlocal new_filenames_list
        nonlocal old_new_files_dict

        # 执行重命名
        do_rename(filenames_list, new_filenames_list, old_new_files_dict)

    do_btn = ttk.Button(frame_1, text='执行重命名', command=do_btn_clicked)
    do_btn.state(['disabled'])
    do_btn.place(relx=0.7, rely=0.2, relwidth=0.3, relheight=0.1)

    # 定义排序方式
    options = ["按名称从A到Z", "按名称从Z到A",
               "按文件大小从大到小", "按文件大小从小到大",
               "按文件类型名从A到Z", "按文件类型名从Z到A",
               "按修改时间从新到旧", "按修改时间从旧到新"]

    combo = ttk.Combobox(frame_1, values=options, font=('Microsoft YaHei UI Light', 12, 'bold'), justify="center")

    combo.place(relwidth=0.4, relheight=0.1, relx=0, rely=0.2)

    # 绑定事件，选择排序方式后，立即展示
    combo.bind("<<ComboboxSelected>>",
               lambda event: on_select(event, combo, filenames_list, text_box, old_new_names_dict))

    # 设置默认选项，"按名称从A到Z"
    combo.current(0)


def on_select(event, combo, disordered_files_path_list, text_box, old_new_name_dict):
    selected_value = combo.get()

    if selected_value == "按文件大小从大到小":
        sort_by_file_size(disordered_files_path_list, text_box, True, old_new_name_dict)
    elif selected_value == "按文件大小从小到大":
        sort_by_file_size(disordered_files_path_list, text_box, False, old_new_name_dict)
    elif selected_value == "按名称从A到Z":
        sort_by_filename(disordered_files_path_list, text_box, True, old_new_name_dict)
    elif selected_value == "按名称从Z到A":
        sort_by_filename(disordered_files_path_list, text_box, False, old_new_name_dict)
    elif selected_value == "按修改时间从新到旧":
        sort_by_file_modification_time(disordered_files_path_list, text_box, True, old_new_name_dict)
    elif selected_value == "按修改时间从旧到新":
        sort_by_file_modification_time(disordered_files_path_list, text_box, False, old_new_name_dict)
    elif selected_value == "按文件类型名从A到Z":
        sort_by_file_type_name(disordered_files_path_list, text_box, False, old_new_name_dict)
    elif selected_value == "按文件类型名从Z到A":
        sort_by_file_type_name(disordered_files_path_list, text_box, True, old_new_name_dict)
    else:
        # 默认按名称从A到Z排序
        sort_by_filename(disordered_files_path_list, text_box, True, old_new_name_dict)


def append_str(filenames_list, frame_2):
    # 插入位置
    pos = tk.StringVar()
    # 插入的字符串
    insert_str = tk.StringVar()

    new_filenames_list = []
    old_new_names_dict = {}
    old_new_files_dict = {}

    if True:
        label_1 = ttk.Label(frame_2, text='插入的位置：')
        label_1.place(relx=0, rely=0, relwidth=0.2, relheight=0.1)
        entry1 = ttk.Entry(frame_2, textvariable=pos)
        entry1.place(relx=0.2, rely=0, relwidth=0.8, relheight=0.1)

        label_2 = ttk.Label(frame_2, text='插入的内容：')
        label_2.place(relx=0, rely=0.1, relwidth=0.2, relheight=0.1)
        entry_2 = ttk.Entry(frame_2, textvariable=insert_str)
        entry_2.place(relx=0.2, rely=0.1, relwidth=0.8, relheight=0.1)

        # 创建一个Text组件
        text_box = tk.Text(frame_2, wrap=tk.NONE, font=('Arial', 20, 'bold'))
        text_box.place(relwidth=0.97, relheight=0.67, relx=0, rely=0.3)

        # 创建竖向滚动条
        v_scrollbar = ttk.Scrollbar(frame_2, orient="vertical", command=text_box.yview)
        v_scrollbar.place(relwidth=0.03, relheight=0.7, relx=0.97, rely=0.3)

        # 创建横向滚动条
        h_scrollbar = ttk.Scrollbar(frame_2, orient="horizontal", command=text_box.xview)
        h_scrollbar.place(relwidth=0.9, relheight=0.03, relx=0, rely=0.97)

        # 配置Text组件的滚动条
        text_box.configure(yscrollcommand=v_scrollbar.set, xscrollcommand=h_scrollbar.set)

    # 默认按照名称从A-Z排序
    sort_by_filename(filenames_list, text_box, flag=True, old_new_name_dict={})

    def preview_btn_clicked():

        nonlocal new_filenames_list
        nonlocal old_new_names_dict
        nonlocal combo
        nonlocal do_btn

        insert_pos = int(pos.get())
        _insert_str = insert_str.get()
        new_filenames_list = []

        # 是否允许替换扩展名
        flag = messagebox.askyesno(message='是否允许替换扩展名？')

        # 插入操作
        for i in filenames_list:
            if flag:
                # 位置超过字符串长度会默认在字符串末尾插入内容
                new_str = i[:insert_pos] + _insert_str + i[insert_pos:]
                new_filenames_list.append(new_str)
            else:
                index1 = i.index('.')
                new_str_0 = i[0:index1]

                new_str = new_str_0[:insert_pos] + _insert_str + new_str_0[insert_pos:] + i[index1:]
                new_filenames_list.append(new_str)

        show_in_text_box(text_box, filenames_list, new_filenames_list, old_new_names_dict)

        combo.current(0)
        do_btn.state(['!disabled'])

    preview_btn = ttk.Button(frame_2, text='预览', command=preview_btn_clicked)
    preview_btn.place(relx=0.4, rely=0.2, relwidth=0.3, relheight=0.1)

    def do_btn_clicked():
        nonlocal new_filenames_list
        nonlocal old_new_files_dict

        # 执行重命名
        do_rename(filenames_list, new_filenames_list, old_new_files_dict)

    do_btn = ttk.Button(frame_2, text='执行', command=do_btn_clicked)
    do_btn.state(['disabled'])
    do_btn.place(relx=0.7, rely=0.2, relwidth=0.3, relheight=0.1)

    # 定义排序方式
    options = ["按名称从A到Z", "按名称从Z到A",
               "按文件大小从大到小", "按文件大小从小到大",
               "按文件类型名从A到Z", "按文件类型名从Z到A",
               "按修改时间从新到旧", "按修改时间从旧到新"]

    combo = ttk.Combobox(frame_2, values=options, font=('Microsoft YaHei UI Light', 12, 'bold'), justify="center")

    combo.place(relwidth=0.4, relheight=0.1, relx=0, rely=0.2)

    # 绑定事件，选择排序方式后，立即展示
    combo.bind("<<ComboboxSelected>>",
               lambda event: on_select(event, combo, filenames_list, text_box, old_new_names_dict))

    # 设置默认选项，"按名称从A到Z"
    combo.current(0)


def serialize(filenames_list, frame_3):
    # 序号起点
    star_num = tk.StringVar()
    # 序号位数
    num_len = tk.StringVar()
    # 增量
    step = tk.StringVar()
    # 前缀字符串
    pre_str = tk.StringVar()
    # 后缀字符串
    suf_str = tk.StringVar()

    old_new_names_dict = {}
    new_filenames_list = []
    old_new_files_dict = {}

    if True:
        label_1 = ttk.Label(frame_3, text='输入起始序号，必须是>=0的整数：')
        label_1.place(relx=0, rely=0, relwidth=0.4, relheight=0.06)

        entry_1 = ttk.Entry(frame_3, textvariable=star_num)
        entry_1.place(relx=0.4, rely=0, relwidth=0.2, relheight=0.06)

        label_2 = ttk.Label(frame_3, text='输入序号的固定位数，必须是>=1的整数：')
        label_2.place(relx=0, rely=0.06, relwidth=0.4, relheight=0.06)

        entry_2 = ttk.Entry(frame_3, textvariable=num_len)
        entry_2.place(relx=0.4, rely=0.06, relwidth=0.2, relheight=0.06)

        label_3 = ttk.Label(frame_3, text='输入递增量，必须是>=1的整数：')
        label_3.place(relx=0, rely=0.12, relwidth=0.4, relheight=0.06)

        entry_3 = ttk.Entry(frame_3, textvariable=step)
        entry_3.place(relx=0.4, rely=0.12, relwidth=0.2, relheight=0.06)

        label_4 = ttk.Label(frame_3, text='输入前缀字符串：')
        label_4.place(relx=0, rely=0.18, relwidth=0.4, relheight=0.06)

        entry_4 = ttk.Entry(frame_3, textvariable=pre_str)
        entry_4.place(relx=0.4, rely=0.18, relwidth=0.2, relheight=0.06)

        label_5 = ttk.Label(frame_3, text='输入后缀字符串：')
        label_5.place(relx=0, rely=0.24, relwidth=0.4, relheight=0.06)

        entry_5 = ttk.Entry(frame_3, textvariable=suf_str)
        entry_5.place(relx=0.4, rely=0.24, relwidth=0.2, relheight=0.06)

        # 创建一个Text组件
        text_box = tk.Text(frame_3, wrap=tk.NONE, font=('Arial', 20, 'bold'))  # wrap=tk.NONE 表示不自动换行
        # text.grid(row=1, column=0, sticky="nsew")
        text_box.place(relwidth=0.97, relheight=0.67, relx=0, rely=0.3)

        # 创建竖向滚动条
        v_scrollbar = ttk.Scrollbar(frame_3, orient="vertical", command=text_box.yview)
        # v_scrollbar.grid(row=0, column=1, sticky="ns")
        v_scrollbar.place(relwidth=0.03, relheight=0.7, relx=0.97, rely=0.3)

        # 创建横向滚动条
        h_scrollbar = ttk.Scrollbar(frame_3, orient="horizontal", command=text_box.xview)
        # h_scrollbar.grid(row=1, column=0, sticky="ew")
        h_scrollbar.place(relwidth=0.9, relheight=0.03, relx=0, rely=0.97)

        # 配置Text组件的滚动条
        text_box.configure(yscrollcommand=v_scrollbar.set, xscrollcommand=h_scrollbar.set)

    # 默认按照名称从A-Z排序
    sort_by_filename(filenames_list, text_box, flag=True, old_new_name_dict={})

    def preview_btn_clicked():

        nonlocal do_btn
        nonlocal combo
        nonlocal filenames_list
        nonlocal new_filenames_list

        _step = int(step.get())
        _pre_str = pre_str.get()
        _suf_str = suf_str.get()

        _num_len = int(num_len.get())
        file_num = len(filenames_list)
        _star_num = int(star_num.get())

        num_list = []
        new_filenames_list = []

        # 是否允许替换扩展名
        flag = messagebox.askyesno(message='是否允许替换扩展名？')

        # 序列化操作
        for i in range(file_num):
            num = (_num_len - len(str(_star_num))) * '0' + str(_star_num)
            num_list.append(num)
            _star_num = int(num) + _step

        if flag:
            for j in num_list:
                new_filenames_list.append(_pre_str + j + _suf_str)
        else:
            for i in range(file_num):
                extension_name = filenames_list[i].split('.')[-1]
                new_filenames_list.append(_pre_str + num_list[i] + _suf_str + '.' + extension_name)

        show_in_text_box(text_box, filenames_list, new_filenames_list, old_new_names_dict)

        combo.current(0)
        do_btn.state(['!disabled'])

    preview_btn = ttk.Button(frame_3, text='预览', command=preview_btn_clicked)
    preview_btn.place(relx=0.6, rely=0, relwidth=0.2, relheight=0.15)

    def do_btn_clicked():
        nonlocal new_filenames_list
        nonlocal filenames_list
        nonlocal old_new_files_dict

        # 执行重命名
        do_rename(filenames_list, new_filenames_list, old_new_files_dict)

    do_btn = ttk.Button(frame_3, text='执行', command=do_btn_clicked)
    do_btn.state(['disabled'])
    do_btn.place(relx=0.8, rely=0, relwidth=0.2, relheight=0.15)

    # 定义排序方式
    options = ["按名称从A到Z", "按名称从Z到A",
               "按文件大小从大到小", "按文件大小从小到大",
               "按文件类型名从A到Z", "按文件类型名从Z到A",
               "按修改时间从新到旧", "按修改时间从旧到新"]

    # 定义下拉框
    combo = ttk.Combobox(frame_3, values=options, font=('Microsoft YaHei UI Light', 12, 'bold'), justify="center")

    # 设置下拉框位置
    combo.place(relwidth=0.4, relheight=0.15, relx=0.6, rely=0.15)

    # 绑定事件，选择排序方式后，立即展示
    combo.bind("<<ComboboxSelected>>",
               lambda event: on_select(event, combo, filenames_list, text_box, old_new_names_dict))

    # 设置默认选项，"按名称从A到Z"
    combo.current(0)


def rtton(old_new_files_dict):
    # 把已经重命名的文件恢复原名
    # revert to the original name

    for k, v in old_new_files_dict:
        try:
            os.rename(v, k)
        except Exception:  # noqa
            messagebox.showinfo(message='很遗憾，重命名失败，且恢复原名失败')
            sys.exit(0)


def batch_rename(files_list):
    global parent_folder

    filenames_list = []

    for i in files_list:
        filenames_list.append(os.path.basename(i))

    if True:
        root = tk.Tk()
        root.title("批量重命名")
        # root = set_container_size(root, 3)
        root.geometry('800x600')
        center_window(root, 800, 600)
        root.attributes('-topmost', 'true')
        # create a notebook
        notebook = ttk.Notebook(root)
        notebook.pack(pady=10, expand=True)

        # create frames
        frame_1 = ttk.Frame(notebook, width=800, height=580)
        frame_2 = ttk.Frame(notebook, width=800, height=580)
        frame_3 = ttk.Frame(notebook, width=800, height=580)

        frame_1.pack(fill='both', expand=True)
        frame_2.pack(fill='both', expand=True)
        frame_3.pack(fill='both', expand=True)

        # add frames to notebook

        notebook.add(frame_1, text='文本替换')
        notebook.add(frame_2, text='指定位置追加文本')
        notebook.add(frame_3, text='序列化')

    # 6.1、替换，是否包括扩展名
    replace_str(filenames_list, frame_1)
    # 6.2、在给定位置追加文本
    append_str(filenames_list, frame_2)
    # 6.3、前面字符-固定位数序号（可设置起点）-后面字符
    serialize(filenames_list, frame_3)

    def on_closing():
        # 关闭窗口并退出程序
        sys.exit(0)

    # 监听窗口关闭事件
    root.protocol("WM_DELETE_WINDOW", on_closing)

    root.mainloop()


if __name__ == '__main__':
    # 排序后的文件名
    ordered_files_list = []

    # 1、运行程序，首先弹出一个弹窗询问“选择文件夹”还是“批量选择文件”
    user_choice = choose_files_or_folder()

    # 2、获取选择对象
    files_list = get_files(user_choice)
    parent_folder = os.path.dirname(files_list[0])

    # 3、在文本框中按默认顺序打印所有选择的文件
    # 4、对文件排序
    # 5、在文本框中打印排序后的文件
    # 6、重命名
    batch_rename(files_list)
